#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "InetAddr.hpp"
#include "Log.hpp"
#include "LockGuard.hpp"
#include "ThreadPool.hpp"
using namespace log_ns;

using route_task_t = std::function<void()>;

class Route {
private:
    void CheckUserinList(const InetAdrr& who) {
        LockGuard lockguard(&_mutex);
        for (auto& user : _user_online) {
            if (user == who) return;
        }
        
        LOG(DEBUG, "%s is not exist, add it now\n", who.AddrString().c_str());
        _user_online.push_back(who);
    }

    void Lineoff(InetAdrr& who) {
        LockGuard lockguard(&_mutex);
        auto it = _user_online.begin();
        while (it != _user_online.end()) {
            if (*it == who) {
                _user_online.erase(it);
                LOG(DEBUG, "%s line off\n", who.AddrString().c_str());
                return;
            }
        }
    }

    void ForwordHelper(int sockfd, const std::string& message, InetAdrr& who) {
        std::string send_message = "[" + who.AddrString() + "]> ";
        send_message += message;
        // 现在将messeage转发出去
        for (auto& user : _user_online) {
            struct sockaddr_in peer = user.Addr();
            socklen_t len = sizeof(peer);
            LOG(INFO, "%s forword to %s\n", send_message.c_str(), user.AddrString().c_str());
            sendto(sockfd, send_message.c_str(), send_message.size(), 0, (struct sockaddr*)&peer, len);
        }
    }

public:
    Route() {
        pthread_mutex_init(&_mutex, nullptr);
    }

    void ForwordMessage(int sockfd, const std::string& message, InetAdrr& who) {
        // 先检查当前用户列表中是否存在who
        CheckUserinList(who);
        
        if (message == "Q" || message == "QUIT") {
            Lineoff(who);
        }

        // 开始转发信息
        // ForwordHelper(sockfd, message, who);
        // 现在开始绑定我们的函数
        route_task_t t = std::bind(&Route::ForwordHelper, this, sockfd, message, who);
        ThreadPool<route_task_t>::GetInstance()->Push(t);
    }

    ~Route() {
        pthread_mutex_destroy(&_mutex);
    }
private:
    // 用户列表
    std::vector<InetAdrr> _user_online;
    pthread_mutex_t _mutex;
};